/*!
 * # 模块 JS:
 *  Mop - 日志管理
 * 
 * # 描述:
 *  向系统管理人员提供查阅数据操作日志的相关功能。
 * 
 * Copyright (c), 上海沃恩信息科技有限公司.
 * All rights reserved.
 * Licensed under BSD (https://www.pittypat.work/bsd.html).
 */

/*
 * @param {Object} $    jQuery 命名空间。
 * @param {Object} $$   pittypat 命名空间。
 * @param {Object} _mod 模块 Apps (应用与功能) 的命名空间。
 * 
 * 使用 pittypat.namespace('...') 以确保 _mod 命名空间是存在的。
 * 
 * 更多说明请参见：
 * https://www.pittypat.work/com/waln/pittypat/coding/help/index.html#js。
 */
(function ($, $$, _mod) {
    'use strict';

    $$.ui.msg = '...';

    /*
     * 为登录用户注册一个处理函数。
     * 由于没有为匿名用户注册处理函数，那么当发现用户尚未登录时，则会默认跳转到首页（登录页）。
     * 
     * 如果需要为匿名用户添加处理逻辑，应该使用如下格式的代码：
     * $$({
     *     authorized: function (_) {
     *         ...
     *     },
     *     anonymous: function (_) {
     *         // 跳转到自定义的登录页面
     *         window.location = '../../../../login.html';
     *     }
     * });
     * 
     * 如果需要自定义登录页面，则可能还需要添加 init 等处理函数。详细帮助请参见：
     * https://www.pittypat.work/com/waln/pittypat/ref/help/pittypat.js.html#pittypat。
     *
     * 参数 _ 的定义如下：
     * {
     *    user:  {Object},  // (只读)当前用户的用户信息
     *    app:   {Object},  // (只读)当前应用的命名空间，如果无法定位，则为 null
     *    mod:   {Object},  // (只读)当前模块的命名空间，如果无法定位，则为 null
     *    init:  {Boolean}, // (只读)是否正在初始化页面
     *    first: {Boolean}, // (只读)是否首次执行 authorized
     *    data:  {any}      // (读写)前述的 data 数据，或 data 函数返回的结果
     * }
     */
    $$(function (_) {
        var
            // 模块 UI 命名空间
            _ui = _mod.ui = _mod.ui || {},
            // 模块 API 命名空间
            _api = _mod.api,
            // 主工作区
            $main = $('.pt-main');

        if (_.init) {
            _ui.opMessage = {
                /*
                 * App 对象对应的 DOM HTML。
                 */
                get html() {
                    return '<article class="pt-row pt-model model-op-message">' +
                        '    <hr />' +
                        '    <header>' +
                        '        <div class="pt-row-icon">' +
                        '            <i class="pt-row-toggle material-icons mdc-ripple-surface mdc-ripple-surface--primary mdc-theme--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">check_box_outline_blank</i>' +
                        '        </div>' +
                        '        <div class="pt-row-info">' +
                        '            <div class="w-9">' +
                        '                <span class="model-prop model-op-message-op-time"></span>' +
                        '                <span class="model-prop model-op-message-summary"></span>' +
                        '            </div>' +
                        '            <div class="w-10">' +
                        '                <span class="model-prop model-op-message-user-name"></span>' +
                        '            </div>' +
                        '            <div class="hidden-phone">' +
                        '                <span class="model-prop model-op-message-table-names"></span>' +
                        '            </div>' +
                        '            <div class="w-20 hidden-phone hidden-tablet">' +
                        '                <span class="model-prop model-op-message-proc-name"></span>' +
                        '            </div>' +
                        '        </div>' +
                        '        <div class="pt-row-more">' +
                        '            <i data-target-dialog="#details-dialog" class="show-details material-icons mdc-ripple-surface mdc-ripple-surface--primary mdc-theme--primary" data-mdc-ripple-is-unbounded data-mdc-auto-init="MDCRipple">' +
                        '                subject' +
                        '            </i>' +
                        '        </div>' +
                        '    </header>' +
                        '</article>';
                },

                /*
                 * 将指定的 App 对象添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args   _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {Number} pos    插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list  要插入的 DOM 列表。
                 */
                insert: function (args, model, pos, $list) {
                    if (!model) {
                        // 没有提供 App 对象
                        return null;
                    }

                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $main.find('>article>section');
                    }

                    if (!$$.util.is.int(pos)) {
                        // 添加到列表最后
                        pos = -1;
                    }

                    // 目前位置上当前元素
                    var $next = pos >= 0 ? $list.children('.model-app').eq(pos) : null,
                        $model = null;

                    if ($next && $next.length) {
                        // 插入到目标元素之前
                        $model = $(_ui.opMessage.html).insertBefore($next);
                    } else {
                        // 添加到列表最后
                        $model = $(_ui.opMessage.html).appendTo($list);
                    }

                    // 将对象属性更新到目标元素
                    return _ui.opMessage.update(args, model, $model, $list).mdcInit();
                },

                /*
                 * 将指定的 App 对象数组添加到指定 DOM 列表的指定位置。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} models 一个 App 对象的数组。
                 * @param {Number} pos   插入位置，非数字将清空现有列表，小于 0 将添加到最后。
                 * @param {jQuery} $list 要插入的 DOM 列表。
                 */
                insertAll: function (args, models, pos, $list) {
                    $list = $main.find('>article>section');

                    if (args.pageIndex === '1') {
                        // 清空现有列表
                        $list.empty();
                        // 添加到列表最后
                        pos = -1;
                    }

                    if (models && models.length) {
                        if (pos <= 0) {
                            // 添加到最前或最后
                            models.each(function (model) {
                                _ui.opMessage.insert(args, model, pos, $list);
                            });
                        } else {
                            // 添加到指定位置
                            models.each(function (model, i) {
                                _ui.opMessage.insert(args, model, pos + i, $list);
                            });
                        }
                    }

                    return $list;
                },

                /*
                 * 将指定的 App 对象更新到现有的 DOM。
                 * 
                 * @param {any}    args  _api.list 的 args 事件创建的参数。
                 * @param {Object} model  一个 App 对象。
                 * @param {jQuery} $model 现有的 DOM。
                 * @param {jQuery} $list 隶属的 DOM 列表。
                 */
                update: function (args, model, $model, $list) {
                    if (!$list || !$list.length) {
                        // 目标元素列表
                        $list = $main.find('>article>section');
                    }

                    if (!$model || !$model.length) {
                        // 没有提供 $model 时根据 model 或 args 查找目标元素
                        $model = $list.children('#model-op-message-' + model.id);
                    }

                    if (model && $model.length) {
                        var $h = $model
                            .attr('id', 'model-op-message-' + model.id)
                            .data('model', model)
                            .children('header');

                        $h.find('.model-op-message-op-time').text($$.util.fmt.minute(model.opTime));
                        $h.find('.model-op-message-user-name').text(model.userName);
                        $h.find('.model-op-message-table-names').text(model.tableNames);
                        $h.find('.model-op-message-proc-name').text(model.procName);
                        $h.find('.model-op-message-summary').text(model.summary);
                    }

                    return $model;
                }
            };

            _api.list
                // 准备参数
                .on('args', function (e) {
                    e.args = {
                        pageIndex: $('#list-page-index').val(),
                        orderDirection: $('#list-order-direction').val(),
                        timeFrom: $('#list-time-from').val(),
                        timeTo: $('#list-time-to').val(),
                        userName: $('#list-user-name').val(),
                        tableNames: $('#list-table-names').val(),
                        procName: $('#list-proc-name').val()
                    };
                })

                // 执行成功
                .on('success', function (e) {
                    // 总行数和已加载行数
                    var $loadedRows = $('#loaded-rows'),
                        $totalRows = $('#total-rows'),
                        totalRows = Long.fromValue(e.result.totalRows),
                        loadedRows = (e.args.pageIndex === '1' ? Long.ZERO : Long.fromValue($loadedRows.text()))
                            .add(e.result.messages.length);

                    $loadedRows.text(loadedRows);
                    $totalRows.text(totalRows);

                    // 如果已经加载的行数等于或超过了总行数，隐藏加载更多按钮
                    $('#load-more').css('display', loadedRows.gte(totalRows) ? 'none' : 'flex');

                    // 显示列表
                    _ui.opMessage.insertAll(e.args, e.result.messages);
                })

                // 执行完毕
                .on('load', function (e) {
                    // 隐藏正在加载的消息
                    $$.ui.msg = '';
                });

            // 排序方向
            $('.pt-order-field').on('click', function (e) {
                e.preventDefault();

                var
                    // 点击的排序字段
                    $me = $(this),
                    // 排序字段上定义的排序方向
                    dir = ($me.attr('data-order-direction') || 'asc').toLowerCase(),
                    // 排序字段上定义的排序名称，如果没有提供，则按默认排序名称排序
                    name = ($me.attr('data-order-name') || '').toLowerCase();

                // 反转排序方向
                dir = dir == 'asc' ? 'desc' : 'asc';
                // 设置排序方向指示图标
                $me.attr('data-order-direction', dir)
                    .children('.material-icons').text('arrow_drop_' + (dir == 'desc' ? 'up' : 'down'));

                // 设置排序条件
                $('#list-order-name').val(name);
                $('#list-order-direction').val(dir);

                // 重置页码
                $('#list-page-index').val(1);
                // 重新加载列表
                $$.ui.msg = '...';
                _api.list();
            });

            // 加载更多
            $('#load-more').on('click', function () {
                var $pi = $('#list-page-index'),
                    pageIndex = Long.fromValue($pi.val()).add(1);

                $pi.val(pageIndex);

                $$.ui.msg = '...';
                _api.list();
            });

            function opTypeName(type) {
                var name = '';

                if (type & 1) {
                    name += '，查询';
                }

                if (type & 2) {
                    name += '，添加';
                }

                if (type & 4) {
                    name += '，更新';
                }

                if (type & 8) {
                    name += '，删除';
                }

                if (type & 16) {
                    name += '，其他';
                }

                return name ? name.substr(1) : '';
            }

            // 搜索对话框
            $('#search-dialog')
                .on('ok', function (e) {
                    // 重置页码
                    $('#list-page-index').val(1);
                    $$.ui.msg = '...';
                    _api.list();
                    e.done = true;
                });

            // 重置搜索对话框
            $('#reset-search').on('click', function () {
                $('#list-time-from').val('');
                $('#list-time-to').val('');
                $('#list-user-name').val('');
                $('#list-table-names').val('');
                $('#list-proc-name').val('');
            });

            // 详细对话框
            $('#details-dialog')
                .on('opening', function (e) {
                    if (typeof e.model.body === 'undefined') {
                        _api.details
                            .one('args', function (de) {
                                de.args = e.model.id;
                            })
                            .one('success', function (de) {
                                e.model.body = de.result || '';
                                $('#details-body').text(e.model.body || e.model.summary);
                            })();
                    }

                    $('#details-op-time').val($$.util.fmt.minute(e.model.opTime));
                    $('#details-user-name').val(e.model.userName);
                    $('#details-table-names').val(e.model.tableNames);
                    $('#details-proc-name').val(e.model.procName);
                    $('#details-op-type').val(opTypeName(e.model.opType) + ' (' + (e.model.success ? '成功' : '失败') + ')');
                    $('#details-body').text(e.model.body || e.model.summary);
                });

            // 全选按钮
            $('.pt-main>.pt-row').on('beforeselect', function (e) {
                e.affectChildren = true;
            });

            // 确定删除按钮的显示状态
            $main
                .on('beforeselect', '.model-op-message', function (e) {
                    e.affectParent = true;
                })
                .on('afterselect', '.model-op-message', function (e) {
                    var has = e.selected || $('.model-op-message.pt-row-selected').length > 0;
                    $('#delete-logs').css('visibility', has ? 'visible' : 'hidden');
                });

            // 删除选中的日志记录
            $('#delete-logs').on('click', function () {
                var ids = [], rows = [];

                $('.model-op-message.pt-row-selected').each(function () {
                    var $row = $(this);
                    ids.push($row.data('model').id);
                    rows.push($row);
                });

                if (ids.length == 0) {
                    $$.ui.msg = '没有选中任何日志记录。';
                    return;
                }

                $$.ui.confirm('确认删除',
                    '您确实要删除选中的 ' + ids.length + ' 条日志记录么？数据被删除后将无法恢复！',
                    function () {
                        $$.ui.msg = '...';
                        _api.delete
                            .one('args', function (e) {
                                e.args = ids.join(',');
                            })
                            .one('success', function (e) {
                                rows.each(function ($row) {
                                    $row.remove();
                                });

                                $$.ui.msg = '';

                                // 重新调整已经加载的行数和总行数
                                var $loadedRows = $('#loaded-rows'),
                                    $totalRows = $('#total-rows'),
                                    totalRows = Long.fromValue($totalRows.text()).sub(ids.length),
                                    loadedRows = Long.fromValue($loadedRows.text()).sub(ids.length);

                                if (loadedRows.lt(0)) {
                                    loadedRows = Long.ZERO;
                                }

                                if (totalRows.lt(0)) {
                                    totalRows = Long.ZERO;
                                }

                                $loadedRows.text(loadedRows);
                                $totalRows.text(totalRows);

                                // 如果已经加载的行数等于或超过了总行数，隐藏加载更多按钮
                                $('#load-more').css('display', loadedRows.gte(totalRows) ? 'none' : 'flex');

                                // 删除后页面上已经不再有选中的记录，隐藏删除按钮，取消全选按钮
                                $('#delete-logs').css('visibility', 'hidden');

                                // 没有任何行被选中
                                $('.pt-main>.pt-row').rowSelected(false);
                            })();
                    });
            });

            // 初始化 mdc
            $main.mdcInit();
        }

        _api.list();
    });
})(jQuery, pittypat, pittypat.namespace('waln.log.mop'));